///////////////////////////////////////////////////////////////////////
// DFileSystemImageEvent.cpp
//
// Wrapper for DFileSystemImageEvents Interface Events
//
// Written by Nic Wilson
//

#include "stdafx.h"
#include "DFileSystemImageEvent.h"
#include "DFileSystemImage.h"

// CDFileSystemImageEvent

IMPLEMENT_DYNAMIC(CDFileSystemImageEvent, CCmdTarget)

BEGIN_INTERFACE_MAP(CDFileSystemImageEvent, CCmdTarget)
	INTERFACE_PART(CDFileSystemImageEvent, IID_IDispatch, FileSystemImageEvents)
	INTERFACE_PART(CDFileSystemImageEvent, IID_DFileSystemImageEvents, FileSystemImageEvents)
END_INTERFACE_MAP()

CDFileSystemImageEvent::CDFileSystemImageEvent()
: m_hNotifyWnd(NULL)
, m_ptinfo(NULL)
, m_dwCookie(0)
, m_pUnkSink(0)
, m_pUnkSrc(0)
{
}

CDFileSystemImageEvent::~CDFileSystemImageEvent()
{
	if (m_dwCookie && (m_pUnkSrc != NULL) && (m_pUnkSink != NULL))
	{
		AfxConnectionUnadvise(m_pUnkSrc, IID_DFileSystemImageEvents, m_pUnkSink, TRUE, m_dwCookie);
	}
}


BEGIN_MESSAGE_MAP(CDFileSystemImageEvent, CCmdTarget)
END_MESSAGE_MAP()



// CDFileSystemImageEvent message handlers

ULONG FAR EXPORT CDFileSystemImageEvent::XFileSystemImageEvents::AddRef()
{
	METHOD_PROLOGUE(CDFileSystemImageEvent, FileSystemImageEvents)
	return pThis->ExternalAddRef();
}
ULONG FAR EXPORT CDFileSystemImageEvent::XFileSystemImageEvents::Release()
{
	METHOD_PROLOGUE(CDFileSystemImageEvent, FileSystemImageEvents)
	return pThis->ExternalRelease();
}
STDMETHODIMP CDFileSystemImageEvent::XFileSystemImageEvents::QueryInterface(REFIID riid,
												   LPVOID FAR* ppvObj)
{
	METHOD_PROLOGUE(CDFileSystemImageEvent, FileSystemImageEvents)
	return (HRESULT)pThis->ExternalQueryInterface(&riid, ppvObj);
}
STDMETHODIMP
CDFileSystemImageEvent::XFileSystemImageEvents::GetTypeInfoCount(UINT FAR* pctinfo)
{
	METHOD_PROLOGUE(CDFileSystemImageEvent, FileSystemImageEvents)
	*pctinfo = 1;
	return NOERROR;
}
STDMETHODIMP CDFileSystemImageEvent::XFileSystemImageEvents::GetTypeInfo(
	UINT itinfo,
	LCID lcid,
	ITypeInfo FAR* FAR* pptinfo)
{
	METHOD_PROLOGUE(CDFileSystemImageEvent, FileSystemImageEvents)
	*pptinfo = NULL;

	if(itinfo != 0)
		return ResultFromScode(DISP_E_BADINDEX);
	pThis->m_ptinfo->AddRef();
	*pptinfo = pThis->m_ptinfo;
	return NOERROR;
}
STDMETHODIMP CDFileSystemImageEvent::XFileSystemImageEvents::GetIDsOfNames(
	REFIID riid,
	OLECHAR FAR* FAR* rgszNames,
	UINT cNames,
	LCID lcid,
	DISPID FAR* rgdispid)
{
	METHOD_PROLOGUE(CDFileSystemImageEvent, FileSystemImageEvents)
	return DispGetIDsOfNames(pThis->m_ptinfo, rgszNames, cNames, rgdispid);
}

STDMETHODIMP CDFileSystemImageEvent::XFileSystemImageEvents::Invoke(
	DISPID dispidMember,
	REFIID riid,
	LCID lcid,
	WORD wFlags,
	DISPPARAMS FAR* pdispparams,
	VARIANT FAR* pvarResult,
	EXCEPINFO FAR* pexcepinfo,
	UINT FAR* puArgErr)
{
	METHOD_PROLOGUE(CDFileSystemImageEvent, FileSystemImageEvents)

	return DispInvoke(&pThis->m_xFileSystemImageEvents, pThis->m_ptinfo,
		dispidMember, wFlags, pdispparams, pvarResult, pexcepinfo, puArgErr);
}

//
///////////////////////////////////////////////////////////////////////
//
// CDFileSystemImageEvent::CreateEventSink
//
// Description:
//			Establishes a link between the CDFileSystemImage(IFileSystemImage)
//			and the CDFileSystemImageEvent(DFileSystemImageEvents) so 
//			CDFileSystemImageEvent can receive Update messages
//
CDFileSystemImageEvent* CDFileSystemImageEvent::CreateEventSink()
{
	// Create the event sink
	CDFileSystemImageEvent* pDFileSystemImageEvent = new CDFileSystemImageEvent();

	pDFileSystemImageEvent->EnableAutomation();
	pDFileSystemImageEvent->ExternalAddRef();

	return pDFileSystemImageEvent;
}

///////////////////////////////////////////////////////////////////////
//
// CDFileSystemImageEvent::ConnectDFileSystemImage
//
// Description:
//			Establishes a connection between the CDFileSystemImage(IFileSystemImage)
//			and the CDFileSystemImageEvent(DFileSystemImageEvents) so 
//			CDFileSystemImageEvent can receive Update messages
//
bool CDFileSystemImageEvent::ConnectDFileSystemImage(CDFileSystemImage* pDFileSystemImage)
{
	m_pUnkSink = GetIDispatch(FALSE);
	m_pUnkSrc = pDFileSystemImage->GetInterface();

	LPTYPELIB ptlib = NULL;
	HRESULT hr = LoadRegTypeLib(LIBID_IMAPI2FS, IMAPI2FS_MajorVersion, IMAPI2FS_MinorVersion, LOCALE_SYSTEM_DEFAULT, &ptlib);
	if (FAILED(hr))
	{
		return false;
	}
	hr = ptlib->GetTypeInfoOfGuid(IID_DFileSystemImageEvents, &m_ptinfo);
    ptlib->Release();
	if (FAILED(hr))
	{
	    return false;
	}

	BOOL bRet = AfxConnectionAdvise(m_pUnkSrc, IID_DFileSystemImageEvents, m_pUnkSink,
		TRUE, &m_dwCookie);
	if (bRet)
	{
		return true;
	}

	return false;
}

///////////////////////////////////////////////////////////////////////
//
// CDFileSystemImageEvent::Update
//
// Description:
//			Receives update notifications from IFileSystemImage
//
STDMETHODIMP_(HRESULT) CDFileSystemImageEvent::XFileSystemImageEvents::Update(IDispatch* objectDispatch, BSTR currentFile, LONG copiedSectors, LONG totalSectors)
{
	METHOD_PROLOGUE(CDFileSystemImageEvent, FileSystemImageEvents)
	HRESULT hr = S_OK;

	IFileSystemImage* DFileSystemImage = NULL;
    hr = objectDispatch->QueryInterface(IID_PPV_ARGS(&DFileSystemImage));

    IMAPI_STATUS imapiStatus = {0};
	
	imapiStatus.currentFile = currentFile;
	imapiStatus.copiedSectors = copiedSectors;
	imapiStatus.totalSectors = totalSectors;
	LRESULT ret = ::SendMessage(pThis->m_hNotifyWnd, WM_IMAPI_FS_UPDATE, IMAPI_FILESYSTEM_FILE_UPDATE, (LPARAM)(LPVOID)&imapiStatus);
	return S_OK;
}

